package dk.itu.KrakMap;

import java.util.*;

/**
 * Enum to represent a given way of travelling, including the speed changes,
 * and limits in terms of which roads can be taken, for this specific TravelType
 *
 * @author ITU-KF04-2011, Group 11
 */
public enum TravelType {
    CAR(
        130,
        new ArrayList<RoadType>(){{
            add(RoadType.Sti);
            add(RoadType.Stitunnel);
            add(RoadType.gaagader);
            add(RoadType.Stednavn);
            add(RoadType.Faergeforbindelse);
        }}),
    BICYCLE(
        30,
        new ArrayList<RoadType>(){{
            add(RoadType.MOTORVEJ);
            add(RoadType.Faergeforbindelse);
        }},
        new HashMap<RoadType, Integer>(){{
            put(RoadType.Sti, 20);
            put(RoadType.Stitunnel,20);
        }}),
    WALK(
        5,
        new ArrayList<RoadType>(){{
           add(RoadType.MOTORVEJ);
           add(RoadType.Faergeforbindelse);
        }}),
    //TODO: Find better solution!
    FERRY(
        50,
        new ArrayList<RoadType>(){{
            add(RoadType.Andenvej);
            add(RoadType.Andenvejafkorsel);
            add(RoadType.Andenvejtunnel);
            add(RoadType.MOTORVEJ);
            add(RoadType.Mindrevejtunnel);
            add(RoadType.Motortrafikvej);
            add(RoadType.Motortrafikvejsafkorsel);
            add(RoadType.Motortrafikvejstunnel);
            add(RoadType.Motorvejsafkorsel);
            add(RoadType.Motorvejstunnel);
            add(RoadType.Primaerrute);
            add(RoadType.Primaervejsafkorsel);
            add(RoadType.Primaervejstunnel);
            add(RoadType.Projandenvej);
            add(RoadType.Projsti);
            add(RoadType.Projvej);
            add(RoadType.Sekundaerrute);
            add(RoadType.Sekundaervejsafkorsel);
            add(RoadType.Sekundaervejstunnel);
            add(RoadType.Stednavn);
            add(RoadType.Sti);
            add(RoadType.Stitunnel);
            add(RoadType.Vej);
            add(RoadType.gaagader);
            add(RoadType.markvej);
            add(RoadType.projmotortrafikvej);
            add(RoadType.projmotorvej);
            add(RoadType.projprimaervej);
            add(RoadType.projsekundaervej);
        }}
    );
    
    private final int maxSpeed;
    private final ArrayList<RoadType> excludedRoadTypes;
    private final HashMap<RoadType, Integer> speedChanges;

    /**
     * create a new TravelType using a maxSpeed, a list of excluded RoadTypes
     * and setting specific speeds to certain RoadTypes.
     * @param maxSpeed int MaxSpeed
     * @param excludedRoadTypes ArrayList<RoadType> roadtypes to be excluded.
     * @param speedChanges HashMap<RoadType,Integer> to set speeds to RoadTypes.
     */
    private TravelType(int maxSpeed, ArrayList<RoadType> excludedRoadTypes, HashMap<RoadType, Integer> speedChanges) {
        this.maxSpeed = maxSpeed;
        excludedRoadTypes.add(RoadType.Projandenvej);
        excludedRoadTypes.add(RoadType.Projsti);
        excludedRoadTypes.add(RoadType.Projvej);
        excludedRoadTypes.add(RoadType.projmotortrafikvej);
        excludedRoadTypes.add(RoadType.projmotorvej);
        excludedRoadTypes.add(RoadType.projprimaervej);
        excludedRoadTypes.add(RoadType.projsekundaervej);
        this.excludedRoadTypes = excludedRoadTypes;
        this.speedChanges = speedChanges;
    }

    /**
     * create a new TravelType with a maxSpeed and a list of excluded Roadtypes
     * @param maxSpeed int maxSpeed
     * @param excludedRoadTypes ArrayList<RoadType> roadtypes to be excluded.
     */
    private TravelType(int maxSpeed, ArrayList<RoadType> excludedRoadTypes) {
        this(maxSpeed, excludedRoadTypes, new HashMap<RoadType, Integer>());
    }

    /**
     * @return the maxSpeed
     */
    public int getMaxSpeed() {
        return maxSpeed;
    }

    /**
     * @return the excludedRoadTypes
     */
    public ArrayList<RoadType> getExcludedRoadTypes() {
        return excludedRoadTypes;
    }

    /**
     * @return the speedChanges
     */
    public HashMap<RoadType, Integer> getSpeedChanges() {
        return speedChanges;
    }
}
